﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Repetition.Persistence;
using Repetition.Domain;

namespace Repetition.Persistence.FluentNHibernate
{
    public class PersistentProblemList : IProblemList
    {
        private IList<Problem> problems = new List<Problem>();
        private IProblemRepository repository;

        public PersistentProblemList()
            : this(new List<Problem>()) { }

        public PersistentProblemList(IProblemRepository repository)
            : this(new List<Problem>(), repository) { }

        public PersistentProblemList(ICollection<Problem> problems)
            : this(problems, new ProblemRepository()) { }

        public PersistentProblemList(ICollection<Problem> problems, IProblemRepository repository)
        {
            LoadCollection(problems);

            this.repository = repository;
        }

        private void LoadCollection(ICollection<Problem> problems)
        {
            this.problems.Clear();

            foreach (var problem in problems)
                this.problems.Add(problem);
        }

        public int Count { get { return problems.Count; } }

        public void Load(ICollection<Subject> subjects)
        {
            var collection = repository.GetBySubjects(subjects);
            LoadCollection(collection);
        }

        public Problem Get(int index)
        {
            if (index < 0)
                return problems[0];
            if (index >= problems.Count)
                return problems[problems.Count - 1];

            return problems[index];
        }

        public void Add(Problem problem)
        {
            repository.Add(problem);
            problems.Add(problem);
        }

        public void SaveChanges(Problem problem)
        {
            repository.Update(problem);
        }

        public void Remove(Problem problem)
        {
            bool wasRemovedFromList = problems.Remove(problem);

            if (wasRemovedFromList)
                repository.Remove(problem);
        }

        public bool HasNext(Problem problem)
        {
            return GetIndex(problem) < problems.Count - 1;
        }

        public bool HasPrevious(Problem problem)
        {
            return GetIndex(problem) > 0;
        }

        public Problem GetNext(Problem problem)
        {
            if (HasNext(problem))
                return problems[GetIndex(problem) + 1];

            return problem;
        }

        public Problem GetPrevious(Problem problem)
        {
            if (HasPrevious(problem))
                return problems[GetIndex(problem) - 1];

            return problem;
        }

        public ICollection<Problem> GetAll()
        {
            return problems;
        }

        public void Dispose()
        {
            repository.Dispose();
        }

        public void Clear()
        {
            problems.Clear();
        }

        private int GetIndex(Problem problem)
        {
            int problemCount = problems.Count;

            for (int i = 0; i < problemCount; i++)
            {
                if (problems[i] == problem)
                    return i;
            }

            throw new KeyNotFoundException();
        }
    }
}
